Introduction
OVCAR4A and 4B both showed a number of mitochondrial pathways that
were downregulated. This notebook looks into the genes driving those
pathways’ regulation. Of note, neither OVCAR4A nor 4B had any
upregulated mitochondrial pathways.
OVCAR4 downregulated mitochondrial pathways
Pulling the genes related to mitochondrial pathways regulated in
OVCAR4.
# Get pathways consistently regulated in either OVCAR4A or OVCAR4B related to mitochondria
pathways_file = "deseq/output/differential_pathways_all_sensitive_resistant_pairs.csv"
pathways = as.data.frame(read.csv(pathways_file, sep = ",", header = TRUE, row.names = 1))
pathways$OVCAR4A_sig_reg = pathways$OVCAR4A_vs_OVCAR4_padj %>%
map_lgl(\(padj) !is.na(padj) && padj < 0.05)
pathways$OVCAR4B_sig_reg = pathways$OVCAR4B_vs_OVCAR4_padj %>%
map_lgl(\(padj) !is.na(padj) && padj < 0.05)
OVCAR4_pathways = pathways[pathways$OVCAR4A_sig_reg == TRUE | pathways$OVCAR4B_sig_reg, c("Description", "OVCAR4A_vs_OVCAR4_padj", "OVCAR4A_vs_OVCAR4_NES", "OVCAR4B_vs_OVCAR4_padj", "OVCAR4B_vs_OVCAR4_NES")]
print(OVCAR4_pathways)
# Save OVCAR4 pathways so that it can be annotated for pathways related to the mitochondria
OVCAR4_pathways_formatted = OVCAR4_pathways
OVCAR4_pathways_formatted$GO_id = rownames(OVCAR4_pathways_formatted)
OVCAR4_pathways_formatted$Mitochondrial = NA
OVCAR4_pathways_formatted = OVCAR4_pathways_formatted[, c("GO_id", "Description", "Mitochondrial")]
write.csv(OVCAR4_pathways_formatted, file = "deseq/output/OVCAR4_sig_regulated_mitochondrial_pathways.csv")
Mitochondrial pathway annotation
Kristin hand-annotated the pathways regulated in either 4A or 4B as
to whether or not each pathway is related to mitochondria. This is saved
as
OVCAR4_sig_regulated_mitochondrial_pathways_annotated.csv
Note: This list of relevant mitochondrial pathways would need to be
updated if the regulated pathways changes.
Mitochondrial genes of interest
Genes of interest are the genes that – for any significantly
regulated pathway in OVCAR4A or OVCAR4B – were part of the core
enrichment genes for that pathway and had a differential expression padj
< 0.005. (Low padj value chosen to get down to a reasonable number of
genes to view plots of.) Core enrichment genes are the most upregulated
genes in upregulated pathways or the most downregulated genes in
downregulated pathways
# Subset only the pathways that are related to the mitochondria
OVCAR4_mitochondrial_pathways = as.data.frame(read.csv("deseq/specific-pathways/OVCAR4_sig_regulated_mitochondrial_pathways_annotated.csv", sep = ",", header = TRUE, row.names = 1))
OVCAR4_mitochondrial_pathways = OVCAR4_mitochondrial_pathways[OVCAR4_mitochondrial_pathways$Mitochondrial %in% c("Y", "y"),]
get_core_mitochondrial_enrichment_genes = function(cellline_pathways_file, deseq_results_file, name) {
cellline_pathways = as.data.frame(read.csv(cellline_pathways_file, sep = ",", header = TRUE, row.names = 1))
cellline_deseq_res = as.data.frame(read.csv(deseq_results_file, sep = ",", header = TRUE, row.names = 1))
cellline_genes_of_interest = c()
for (row in 1:nrow(OVCAR4_mitochondrial_pathways)) {
id = rownames(OVCAR4_mitochondrial_pathways)[row]
if (id %in% rownames(cellline_pathways)) {
core_enrichment_genes = str_split(cellline_pathways[rownames(cellline_pathways) == id, "core_enrichment_genes"], "/")[[1]]
# Because there were 200-300 core enrichment genes related to mitochondrial pathways in OVCAR4 generally, we want to have a stricter definition of our genes of interest
core_genes_res = cellline_deseq_res[rownames(cellline_deseq_res) %in% core_enrichment_genes, c("log2FoldChange", "padj")]
genes_of_interest = core_genes_res[!is.na(core_genes_res$padj) & core_genes_res$padj < 0.005,]
cellline_genes_of_interest = c(cellline_genes_of_interest, rownames(genes_of_interest))
}
}
if (length(cellline_genes_of_interest) > 0) {
df = as.data.frame(table(cellline_genes_of_interest))
colnames(df) = c("gene", name)
return(df)
} else {
return(data.frame(gene = c(),
count = c()))
}
}
df_1 = get_core_mitochondrial_enrichment_genes("deseq/output/OVCAR4A_vs_OVCAR4_significantly_downregulated_pathways.csv",
"deseq/output/OVCAR4A_vs_OVCAR4_deseq_results.csv",
"important_in_4A_down_pathways")
df_2 = get_core_mitochondrial_enrichment_genes("deseq/output/OVCAR4B_vs_OVCAR4_significantly_downregulated_pathways.csv",
"deseq/output/OVCAR4B_vs_OVCAR4_deseq_results.csv",
"important_in_4B_down_pathways")
df_3 = get_core_mitochondrial_enrichment_genes("deseq/output/OVCAR4A_vs_OVCAR4_significantly_upregulated_pathways.csv",
"deseq/output/OVCAR4A_vs_OVCAR4_deseq_results.csv",
"important_in_4A_up_pathways")
df_4 = as.data.frame(get_core_mitochondrial_enrichment_genes("deseq/output/OVCAR4B_vs_OVCAR4_significantly_upregulated_pathways.csv",
"deseq/output/OVCAR4B_vs_OVCAR4_deseq_results.csv",
"important_in_4B_up_pathways"))
genes_of_interest = merge(df_1, df_2, by = "gene", all = TRUE)
if (nrow(df_3) != 0) {
print("Upregulated genes found! Will need to update the titles of the plots")
genes_of_interest = merge(genes_of_interest, df_3, by = "gene", all = TRUE)
}
if (nrow(df_4) != 0) {
print("Upregulated genes found! Will need to update the titles of the plots")
genes_of_interest = merge(genes_of_interest, df_4, by = "gene", all = TRUE)
}
# Replace all NA values with 0 in the entire data frame
genes_of_interest <- replace(genes_of_interest, is.na(genes_of_interest), 0)
print(genes_of_interest)
Plot the genes of interest important for regulated mitochondrial
pathways in OVCAR4 resistant lines
Need to access the deseq gene-level data to include padj values per
cellline in the plots
# Need Deseq gene data for significance of each gene within a cellline
gene_deseq_file = "deseq/output/differential_gene_expression_all_sensitive_resistant_pairs.csv"
Restarting R session...
Plots based on the transcripts per million data for the genes driving
the mitochondrial pathways. Note: Would need to update title if the
regulated paths change and there are upregulated mitochondrial paths
TPM.log <- as.data.frame(TPM.log)
TPM.log.genes.interesting <- cbind(metadata.all, as.data.frame(t(TPM.log[rownames(TPM.log) %in% genes_of_interest$gene,])))
# To plot each gene separately:
for(row in 1:nrow(genes_of_interest))
{
gene = as.character(genes_of_interest[row, "gene"])
num_4A_down = as.numeric(genes_of_interest[row, "important_in_4A_down_pathways"])
num_4B_down = as.numeric(genes_of_interest[row, "important_in_4B_down_pathways"])
# title = str_interp("${gene} (# downregulated paths affected: 4A - ${num_4A_down}; 4B - ${num_4B_down}. upreg paths: none)")
title = gene
plotData <- TPM.log.genes.interesting[, c("CellLine", "IsoLine", gene)]
colnames(plotData)[3] <- "log.TPM"
# Collect significance data for each cellline
sigData <- data.frame(CellLine = unique(plotData$CellLine))
sigData$significant = sigData$CellLine %>%
map_lgl(\(cellline) !is.na(padj_gene_data[gene, cellline]) && (padj_gene_data[gene, cellline] < 0.05))
plotData$significance = rownames(plotData) %>%
map_chr(\(rowname) {
cellline = plotData[rowname, "CellLine"]
significance = sigData[sigData$CellLine == cellline, "significant"]
label = ifelse(!is.na(significance) && significance, "*", "")
return(label)
})
plotData$sig_height = rownames(plotData) %>% # Label significance 15% higher than highest value
map_dbl(\(rowname) {
cellline = plotData[rowname, "CellLine"]
isoline = plotData[rowname, "IsoLine"]
rep_values = plotData[plotData$CellLine == cellline, "log.TPM"]
isoline_values = plotData[plotData$IsoLine == isoline, "log.TPM"]
height = min(isoline_values) + 1.15 * (max(rep_values) - min(isoline_values))
return(height)
})
plotData$label_height = rownames(plotData) %>% # Label name of cellline 10% higher than highest value
map_dbl(\(rowname) {
cellline = plotData[rowname, "CellLine"]
isoline = plotData[rowname, "IsoLine"]
rep_values = plotData[plotData$CellLine == cellline, "log.TPM"]
isoline_values = plotData[plotData$IsoLine == isoline, "log.TPM"]
height = min(isoline_values) + 1.10 * (max(rep_values) - min(isoline_values))
return(height)
})
# For setting ylim
range_values = max(max(plotData$log.TPM), max(plotData$sig_height)) - min(plotData$log.TPM)
print(
ggplot(plotData, aes(CellLine, log.TPM, color = CellLine,)) +
geom_beeswarm(alpha = 0.3) +
geom_boxplot(outlier.shape = NA, fill = NA) +
geom_text(y = plotData$sig_height, size = 10, label = plotData$significance) +
geom_text(y = plotData$label_height, size = 2, label = plotData$CellLine) +
ylim(min(plotData$log.TPM) - 0.1 * range_values, max(plotData$log.TPM) + 0.15 * range_values) +
theme_classic() +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank()) +
ggtitle(title))
}

































































LS0tCnRpdGxlOiAiR2VuZXMgcmVndWxhdGluZyBtaXRvY2hvbmRyaWFsIHBhdGh3YXlzIGluIE9WQ0FSIDRBIGFuZCA0QiIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgSW50cm9kdWN0aW9uCgpPVkNBUjRBIGFuZCA0QiBib3RoIHNob3dlZCBhIG51bWJlciBvZiBtaXRvY2hvbmRyaWFsIHBhdGh3YXlzIHRoYXQgd2VyZSBkb3ducmVndWxhdGVkLiBUaGlzIG5vdGVib29rIGxvb2tzIGludG8gdGhlIGdlbmVzIGRyaXZpbmcgdGhvc2UgcGF0aHdheXMnIHJlZ3VsYXRpb24uIE9mIG5vdGUsIG5laXRoZXIgT1ZDQVI0QSBub3IgNEIgaGFkIGFueSB1cHJlZ3VsYXRlZCBtaXRvY2hvbmRyaWFsIHBhdGh3YXlzLgoKIyMgSW5wdXRzCgpJbnB1dHMgY29uc2lzdGVkIG9mCgotICAgTWV0YWRhdGEgc3ByZWFkc2hlZXQgZm9yIERFU2VxMgotICAgc2FsbW9uLm1lcmdlZC5nZW5lX3RwbS50c3YKLSAgIFJlc3VsdHMgZnJvbSBkZXNlcS1hbmFseXNpcy5SbWQKCmBgYHtyIGxvYWQgcGFja2FnZXMsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShERVNlcTIpCmxpYnJhcnkodnNuKQpsaWJyYXJ5KHBoZWF0bWFwKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeShnZ3JlcGVsKQpsaWJyYXJ5KGJpb21hUnQpCmxpYnJhcnkoREVTZXFBbmFseXNpcykKbGlicmFyeShVcFNldFIpCmxpYnJhcnkoZ3Byb2ZpbGVyMikKbGlicmFyeShycnZnbykKbGlicmFyeShHTy5kYikKbGlicmFyeShnZ2ZvcnRpZnkpCkdPIDwtIGFzLmxpc3QoR09URVJNKQpsaWJyYXJ5KGNsdXN0ZXJQcm9maWxlcikKbGlicmFyeShlbnJpY2hwbG90KQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeSgib3JnLkhzLmVnLmRiIikKbGlicmFyeShnZ2JlZXN3YXJtKQpsaWJyYXJ5KGdnZm9yY2UpCmBgYAoKIyMjIFJlYWQgaW4gbWV0YWRhdGEgdGFibGUKCmBgYHtyfQpzZW5zaXRpdmVfcmVzaXN0YW50X3BhaXJzIDwtIGMoIk9WQ0FSM0FfdnNfT1ZDQVIzIiwgIk9WQ0FSM0JfdnNfT1ZDQVIzIiwgIk9WQ0FSNEFfdnNfT1ZDQVI0IiwgIk9WQ0FSNEJfdnNfT1ZDQVI0IiwgIlBFQTJfdnNfUEVBMSIsICJQRU82X3ZzX1BFTzEiLCAiUEVPNF92c19QRU8xIikKCmlzb2xpbmVzIDwtIGRhdGEuZnJhbWUocGFpciA9IHNlbnNpdGl2ZV9yZXNpc3RhbnRfcGFpcnMsCiAgICAgICAgICAgICAgICAgICAgICAgaXNvbGluZSA9IGMoIk9WQ0FSMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9WQ0FSMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9WQ0FSNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9WQ0FSNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBFQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBFTyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBFTyIpKQpgYGAKCmBgYHtyIGxvYWQgbWV0YXRhYmxlfQptZXRhZGF0YS5hbGwgPC0gYXMuZGF0YS5mcmFtZShyZWFkLnRhYmxlKCJkZXNlcS9tZXRhZGF0YS5jc3YiLCBzZXAgPSAiLCIsIGhlYWRlciA9IFRSVUUpKQpyb3duYW1lcyhtZXRhZGF0YS5hbGwpIDwtIG1ldGFkYXRhLmFsbCRTaG9ydE5hbWUKCiMgU2hvdWxkIHB1dCB0aGlzIGluIHRoZSBtZXRhZGF0YSBmaWxlLCBidXQganVzdCBkb2luZyB0aGlzIHRvIHNhdmUgdGltZQpmb3IgKHJvdyBpbiAxOm5yb3cobWV0YWRhdGEuYWxsKSkgewogICAgaXNvZ2VuaWNSYW5rIDwtIDEKICAgIHJlc2lzdGFudCA8LSAwCiAgICBpZiAobWV0YWRhdGEuYWxsJENlbGxMaW5lW3Jvd10gJWluJSBsaXN0KCJPVkNBUjNBIiwgIk9WQ0FSNEEiLCAiUEVBMiIsICJQRU80IikpIHsKICAgICAgaXNvZ2VuaWNSYW5rIDwtIDIKICAgICAgcmVzaXN0YW50IDwtIDEKICAgIH0gZWxzZSBpZiAobWV0YWRhdGEuYWxsJENlbGxMaW5lW3Jvd10gJWluJSBsaXN0KCJPVkNBUjNCIiwgIk9WQ0FSNEIiLCAiUEVPNiIpKSB7CiAgICAgIGlzb2dlbmljUmFuayA8LSAzCiAgICAgIHJlc2lzdGFudCA8LSAxCiAgICB9CiAgICBtZXRhZGF0YS5hbGwkSXNvZ2VuaWNSYW5rW3Jvd10gPC0gaXNvZ2VuaWNSYW5rCiAgICBtZXRhZGF0YS5hbGwkUmVzaXN0YW50W3Jvd10gPC0gcmVzaXN0YW50Cn0KbWV0YWRhdGEuYWxsCmBgYAoKIyMjIExvYWQgVFBNIG1hdHJpeApgYGB7cn0KVFBNIDwtIGFzLm1hdHJpeChyZWFkLmRlbGltKCIuLi9zdGFyX3NhbG1vbi9zYWxtb24ubWVyZ2VkLmdlbmVfdHBtLnRzdiIsIHNlcD0iXHQiLCByb3cubmFtZXM9ImdlbmVfaWQiKSkKVFBNIDwtIFRQTVssLTFdClRQTSA8LSBtYXRyaXgoYXMubnVtZXJpYyhUUE0pLCBuY29sID0gbmNvbChUUE0pLCBkaW1uYW1lcyA9IGxpc3Qocm93bmFtZXMoVFBNKSwgY29sbmFtZXMoVFBNKSkpClRQTS5sb2cgPC0gbG9nKFRQTSArIDEpCmNvbG5hbWVzKFRQTS5sb2cpIDwtIG1ldGFkYXRhLmFsbCRTaG9ydE5hbWUKYXMuZGF0YS5mcmFtZShUUE0ubG9nKQpgYGAKCiMjIE9WQ0FSNCBkb3ducmVndWxhdGVkIG1pdG9jaG9uZHJpYWwgcGF0aHdheXMKClB1bGxpbmcgdGhlIGdlbmVzIHJlbGF0ZWQgdG8gbWl0b2Nob25kcmlhbCBwYXRod2F5cyByZWd1bGF0ZWQgaW4gT1ZDQVI0LgoKYGBge3J9CiMgR2V0IHBhdGh3YXlzIGNvbnNpc3RlbnRseSByZWd1bGF0ZWQgaW4gZWl0aGVyIE9WQ0FSNEEgb3IgT1ZDQVI0QiByZWxhdGVkIHRvIG1pdG9jaG9uZHJpYQpwYXRod2F5c19maWxlID0gImRlc2VxL291dHB1dC9kaWZmZXJlbnRpYWxfcGF0aHdheXNfYWxsX3NlbnNpdGl2ZV9yZXNpc3RhbnRfcGFpcnMuY3N2IgpwYXRod2F5cyA9IGFzLmRhdGEuZnJhbWUocmVhZC5jc3YocGF0aHdheXNfZmlsZSwgc2VwID0gIiwiLCBoZWFkZXIgPSBUUlVFLCByb3cubmFtZXMgPSAxKSkKCnBhdGh3YXlzJE9WQ0FSNEFfc2lnX3JlZyA9IHBhdGh3YXlzJE9WQ0FSNEFfdnNfT1ZDQVI0X3BhZGogJT4lCiAgbWFwX2xnbChcKHBhZGopICFpcy5uYShwYWRqKSAmJiBwYWRqIDwgMC4wNSkKcGF0aHdheXMkT1ZDQVI0Ql9zaWdfcmVnID0gcGF0aHdheXMkT1ZDQVI0Ql92c19PVkNBUjRfcGFkaiAlPiUKICBtYXBfbGdsKFwocGFkaikgIWlzLm5hKHBhZGopICYmIHBhZGogPCAwLjA1KQpPVkNBUjRfcGF0aHdheXMgPSBwYXRod2F5c1twYXRod2F5cyRPVkNBUjRBX3NpZ19yZWcgPT0gVFJVRSB8IHBhdGh3YXlzJE9WQ0FSNEJfc2lnX3JlZywgYygiRGVzY3JpcHRpb24iLCAiT1ZDQVI0QV92c19PVkNBUjRfcGFkaiIsICJPVkNBUjRBX3ZzX09WQ0FSNF9ORVMiLCAiT1ZDQVI0Ql92c19PVkNBUjRfcGFkaiIsICJPVkNBUjRCX3ZzX09WQ0FSNF9ORVMiKV0KCnByaW50KE9WQ0FSNF9wYXRod2F5cykKCiMgU2F2ZSBPVkNBUjQgcGF0aHdheXMgc28gdGhhdCBpdCBjYW4gYmUgYW5ub3RhdGVkIGZvciBwYXRod2F5cyByZWxhdGVkIHRvIHRoZSBtaXRvY2hvbmRyaWEKT1ZDQVI0X3BhdGh3YXlzX2Zvcm1hdHRlZCA9IE9WQ0FSNF9wYXRod2F5cwpPVkNBUjRfcGF0aHdheXNfZm9ybWF0dGVkJEdPX2lkID0gcm93bmFtZXMoT1ZDQVI0X3BhdGh3YXlzX2Zvcm1hdHRlZCkKT1ZDQVI0X3BhdGh3YXlzX2Zvcm1hdHRlZCRNaXRvY2hvbmRyaWFsID0gTkEKT1ZDQVI0X3BhdGh3YXlzX2Zvcm1hdHRlZCA9IE9WQ0FSNF9wYXRod2F5c19mb3JtYXR0ZWRbLCBjKCJHT19pZCIsICJEZXNjcmlwdGlvbiIsICJNaXRvY2hvbmRyaWFsIildCndyaXRlLmNzdihPVkNBUjRfcGF0aHdheXNfZm9ybWF0dGVkLCBmaWxlID0gImRlc2VxL291dHB1dC9PVkNBUjRfc2lnX3JlZ3VsYXRlZF9taXRvY2hvbmRyaWFsX3BhdGh3YXlzLmNzdiIpCmBgYAojIyMgTWl0b2Nob25kcmlhbCBwYXRod2F5IGFubm90YXRpb24KCktyaXN0aW4gaGFuZC1hbm5vdGF0ZWQgdGhlIHBhdGh3YXlzIHJlZ3VsYXRlZCBpbiBlaXRoZXIgNEEgb3IgNEIgYXMgdG8gd2hldGhlciBvciBub3QgZWFjaCBwYXRod2F5IGlzIHJlbGF0ZWQgdG8gbWl0b2Nob25kcmlhLiBUaGlzIGlzIHNhdmVkIGFzIGBPVkNBUjRfc2lnX3JlZ3VsYXRlZF9taXRvY2hvbmRyaWFsX3BhdGh3YXlzX2Fubm90YXRlZC5jc3ZgCk5vdGU6IFRoaXMgbGlzdCBvZiByZWxldmFudCBtaXRvY2hvbmRyaWFsIHBhdGh3YXlzIHdvdWxkIG5lZWQgdG8gYmUgdXBkYXRlZCBpZiB0aGUgcmVndWxhdGVkIHBhdGh3YXlzIGNoYW5nZXMuCgojIyBNaXRvY2hvbmRyaWFsIGdlbmVzIG9mIGludGVyZXN0CgpHZW5lcyBvZiBpbnRlcmVzdCBhcmUgdGhlIGdlbmVzIHRoYXQgLS0gZm9yIGFueSBzaWduaWZpY2FudGx5IHJlZ3VsYXRlZCBwYXRod2F5IGluIE9WQ0FSNEEgb3IgT1ZDQVI0QiAtLSB3ZXJlIHBhcnQgb2YgdGhlIGNvcmUgZW5yaWNobWVudCBnZW5lcyBmb3IgdGhhdCBwYXRod2F5IGFuZCBoYWQgYSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBwYWRqIDwgMC4wMDUuIChMb3cgcGFkaiB2YWx1ZSBjaG9zZW4gdG8gZ2V0IGRvd24gdG8gYSByZWFzb25hYmxlIG51bWJlciBvZiBnZW5lcyB0byB2aWV3IHBsb3RzIG9mLikgQ29yZSBlbnJpY2htZW50IGdlbmVzIGFyZSB0aGUgbW9zdCB1cHJlZ3VsYXRlZCBnZW5lcyBpbiB1cHJlZ3VsYXRlZCBwYXRod2F5cyBvciB0aGUgbW9zdCBkb3ducmVndWxhdGVkIGdlbmVzIGluIGRvd25yZWd1bGF0ZWQgcGF0aHdheXMKCmBgYHtyfQojIFN1YnNldCBvbmx5IHRoZSBwYXRod2F5cyB0aGF0IGFyZSByZWxhdGVkIHRvIHRoZSBtaXRvY2hvbmRyaWEKT1ZDQVI0X21pdG9jaG9uZHJpYWxfcGF0aHdheXMgPSBhcy5kYXRhLmZyYW1lKHJlYWQuY3N2KCJkZXNlcS9zcGVjaWZpYy1wYXRod2F5cy9PVkNBUjRfc2lnX3JlZ3VsYXRlZF9taXRvY2hvbmRyaWFsX3BhdGh3YXlzX2Fubm90YXRlZC5jc3YiLCBzZXAgPSAiLCIsIGhlYWRlciA9IFRSVUUsIHJvdy5uYW1lcyA9IDEpKQpPVkNBUjRfbWl0b2Nob25kcmlhbF9wYXRod2F5cyA9IE9WQ0FSNF9taXRvY2hvbmRyaWFsX3BhdGh3YXlzW09WQ0FSNF9taXRvY2hvbmRyaWFsX3BhdGh3YXlzJE1pdG9jaG9uZHJpYWwgJWluJSBjKCJZIiwgInkiKSxdCgpnZXRfY29yZV9taXRvY2hvbmRyaWFsX2VucmljaG1lbnRfZ2VuZXMgPSBmdW5jdGlvbihjZWxsbGluZV9wYXRod2F5c19maWxlLCBkZXNlcV9yZXN1bHRzX2ZpbGUsIG5hbWUpIHsKICBjZWxsbGluZV9wYXRod2F5cyA9IGFzLmRhdGEuZnJhbWUocmVhZC5jc3YoY2VsbGxpbmVfcGF0aHdheXNfZmlsZSwgc2VwID0gIiwiLCBoZWFkZXIgPSBUUlVFLCByb3cubmFtZXMgPSAxKSkKICBjZWxsbGluZV9kZXNlcV9yZXMgPSBhcy5kYXRhLmZyYW1lKHJlYWQuY3N2KGRlc2VxX3Jlc3VsdHNfZmlsZSwgc2VwID0gIiwiLCBoZWFkZXIgPSBUUlVFLCByb3cubmFtZXMgPSAxKSkKICAKICBjZWxsbGluZV9nZW5lc19vZl9pbnRlcmVzdCA9IGMoKQogIAogIGZvciAocm93IGluIDE6bnJvdyhPVkNBUjRfbWl0b2Nob25kcmlhbF9wYXRod2F5cykpIHsKICAgIGlkID0gcm93bmFtZXMoT1ZDQVI0X21pdG9jaG9uZHJpYWxfcGF0aHdheXMpW3Jvd10KICAgIAogICAgaWYgKGlkICVpbiUgcm93bmFtZXMoY2VsbGxpbmVfcGF0aHdheXMpKSB7CiAgICAgIGNvcmVfZW5yaWNobWVudF9nZW5lcyA9IHN0cl9zcGxpdChjZWxsbGluZV9wYXRod2F5c1tyb3duYW1lcyhjZWxsbGluZV9wYXRod2F5cykgPT0gaWQsICJjb3JlX2VucmljaG1lbnRfZ2VuZXMiXSwgIi8iKVtbMV1dCiAgICAgICMgQmVjYXVzZSB0aGVyZSB3ZXJlIDIwMC0zMDAgY29yZSBlbnJpY2htZW50IGdlbmVzIHJlbGF0ZWQgdG8gbWl0b2Nob25kcmlhbCBwYXRod2F5cyBpbiBPVkNBUjQgZ2VuZXJhbGx5LCB3ZSB3YW50IHRvIGhhdmUgYSBzdHJpY3RlciBkZWZpbml0aW9uIG9mIG91ciBnZW5lcyBvZiBpbnRlcmVzdAogICAgICBjb3JlX2dlbmVzX3JlcyA9IGNlbGxsaW5lX2Rlc2VxX3Jlc1tyb3duYW1lcyhjZWxsbGluZV9kZXNlcV9yZXMpICVpbiUgY29yZV9lbnJpY2htZW50X2dlbmVzLCBjKCJsb2cyRm9sZENoYW5nZSIsICJwYWRqIildCiAgICAgIGdlbmVzX29mX2ludGVyZXN0ID0gY29yZV9nZW5lc19yZXNbIWlzLm5hKGNvcmVfZ2VuZXNfcmVzJHBhZGopICYgY29yZV9nZW5lc19yZXMkcGFkaiA8IDAuMDA1LF0KICAgICAgCiAgICAgIGNlbGxsaW5lX2dlbmVzX29mX2ludGVyZXN0ID0gYyhjZWxsbGluZV9nZW5lc19vZl9pbnRlcmVzdCwgcm93bmFtZXMoZ2VuZXNfb2ZfaW50ZXJlc3QpKQogICAgfQogIH0KICAKICBpZiAobGVuZ3RoKGNlbGxsaW5lX2dlbmVzX29mX2ludGVyZXN0KSA+IDApIHsKICAgIGRmID0gYXMuZGF0YS5mcmFtZSh0YWJsZShjZWxsbGluZV9nZW5lc19vZl9pbnRlcmVzdCkpCiAgICBjb2xuYW1lcyhkZikgPSBjKCJnZW5lIiwgbmFtZSkKICAgIHJldHVybihkZikKICB9IGVsc2UgewogICAgcmV0dXJuKGRhdGEuZnJhbWUoZ2VuZSA9IGMoKSwKICAgICAgICAgICAgICAgICAgICAgIGNvdW50ID0gYygpKSkKICB9CiAgCn0KYGBgCgpgYGB7cn0KCmRmXzEgPSBnZXRfY29yZV9taXRvY2hvbmRyaWFsX2VucmljaG1lbnRfZ2VuZXMoImRlc2VxL291dHB1dC9PVkNBUjRBX3ZzX09WQ0FSNF9zaWduaWZpY2FudGx5X2Rvd25yZWd1bGF0ZWRfcGF0aHdheXMuY3N2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImRlc2VxL291dHB1dC9PVkNBUjRBX3ZzX09WQ0FSNF9kZXNlcV9yZXN1bHRzLmNzdiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJpbXBvcnRhbnRfaW5fNEFfZG93bl9wYXRod2F5cyIpCgpkZl8yID0gZ2V0X2NvcmVfbWl0b2Nob25kcmlhbF9lbnJpY2htZW50X2dlbmVzKCJkZXNlcS9vdXRwdXQvT1ZDQVI0Ql92c19PVkNBUjRfc2lnbmlmaWNhbnRseV9kb3ducmVndWxhdGVkX3BhdGh3YXlzLmNzdiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJkZXNlcS9vdXRwdXQvT1ZDQVI0Ql92c19PVkNBUjRfZGVzZXFfcmVzdWx0cy5jc3YiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiaW1wb3J0YW50X2luXzRCX2Rvd25fcGF0aHdheXMiKQoKZGZfMyA9IGdldF9jb3JlX21pdG9jaG9uZHJpYWxfZW5yaWNobWVudF9nZW5lcygiZGVzZXEvb3V0cHV0L09WQ0FSNEFfdnNfT1ZDQVI0X3NpZ25pZmljYW50bHlfdXByZWd1bGF0ZWRfcGF0aHdheXMuY3N2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImRlc2VxL291dHB1dC9PVkNBUjRBX3ZzX09WQ0FSNF9kZXNlcV9yZXN1bHRzLmNzdiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJpbXBvcnRhbnRfaW5fNEFfdXBfcGF0aHdheXMiKQoKZGZfNCA9IGFzLmRhdGEuZnJhbWUoZ2V0X2NvcmVfbWl0b2Nob25kcmlhbF9lbnJpY2htZW50X2dlbmVzKCJkZXNlcS9vdXRwdXQvT1ZDQVI0Ql92c19PVkNBUjRfc2lnbmlmaWNhbnRseV91cHJlZ3VsYXRlZF9wYXRod2F5cy5jc3YiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZGVzZXEvb3V0cHV0L09WQ0FSNEJfdnNfT1ZDQVI0X2Rlc2VxX3Jlc3VsdHMuY3N2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImltcG9ydGFudF9pbl80Ql91cF9wYXRod2F5cyIpKQoKZ2VuZXNfb2ZfaW50ZXJlc3QgPSBtZXJnZShkZl8xLCBkZl8yLCBieSA9ICJnZW5lIiwgYWxsID0gVFJVRSkKCmlmIChucm93KGRmXzMpICE9IDApIHsKICBwcmludCgiVXByZWd1bGF0ZWQgZ2VuZXMgZm91bmQhIFdpbGwgbmVlZCB0byB1cGRhdGUgdGhlIHRpdGxlcyBvZiB0aGUgcGxvdHMiKQogIGdlbmVzX29mX2ludGVyZXN0ID0gbWVyZ2UoZ2VuZXNfb2ZfaW50ZXJlc3QsIGRmXzMsIGJ5ID0gImdlbmUiLCBhbGwgPSBUUlVFKQp9CgppZiAobnJvdyhkZl80KSAhPSAwKSB7CiAgcHJpbnQoIlVwcmVndWxhdGVkIGdlbmVzIGZvdW5kISBXaWxsIG5lZWQgdG8gdXBkYXRlIHRoZSB0aXRsZXMgb2YgdGhlIHBsb3RzIikKICBnZW5lc19vZl9pbnRlcmVzdCA9IG1lcmdlKGdlbmVzX29mX2ludGVyZXN0LCBkZl80LCBieSA9ICJnZW5lIiwgYWxsID0gVFJVRSkKfQoKIyBSZXBsYWNlIGFsbCBOQSB2YWx1ZXMgd2l0aCAwIGluIHRoZSBlbnRpcmUgZGF0YSBmcmFtZQpnZW5lc19vZl9pbnRlcmVzdCA8LSByZXBsYWNlKGdlbmVzX29mX2ludGVyZXN0LCBpcy5uYShnZW5lc19vZl9pbnRlcmVzdCksIDApCgpwcmludChnZW5lc19vZl9pbnRlcmVzdCkKCmBgYAoKIyMgUGxvdCB0aGUgZ2VuZXMgb2YgaW50ZXJlc3QgaW1wb3J0YW50IGZvciByZWd1bGF0ZWQgbWl0b2Nob25kcmlhbCBwYXRod2F5cyBpbiBPVkNBUjQgcmVzaXN0YW50IGxpbmVzCgpOZWVkIHRvIGFjY2VzcyB0aGUgZGVzZXEgZ2VuZS1sZXZlbCBkYXRhIHRvIGluY2x1ZGUgcGFkaiB2YWx1ZXMgcGVyIGNlbGxsaW5lIGluIHRoZSBwbG90cwpgYGB7cn0KIyBOZWVkIERlc2VxIGdlbmUgZGF0YSBmb3Igc2lnbmlmaWNhbmNlIG9mIGVhY2ggZ2VuZSB3aXRoaW4gYSBjZWxsbGluZQpnZW5lX2Rlc2VxX2ZpbGUgPSAiZGVzZXEvb3V0cHV0L2RpZmZlcmVudGlhbF9nZW5lX2V4cHJlc3Npb25fYWxsX3NlbnNpdGl2ZV9yZXNpc3RhbnRfcGFpcnMuY3N2IgpnZW5lX2Rlc2VxID0gYXMuZGF0YS5mcmFtZShyZWFkLmNzdihnZW5lX2Rlc2VxX2ZpbGUsIHNlcCA9ICIsIiwgaGVhZGVyID0gVFJVRSwgcm93Lm5hbWVzID0gMSkpCnBhZGpfZ2VuZV9kYXRhIDwtIGdlbmVfZGVzZXEgJT4lCiAgc2VsZWN0KGNvbnRhaW5zKCJwYWRqIikpCgojIFJlZm9ybWF0IGNvbHVtbiBuYW1lcyB0byBqdXN0IHVzZSB0aGUgcmVzaXN0YW50IGNlbGxsaW5lCmNvbG5hbWVzKHBhZGpfZ2VuZV9kYXRhKSA9IGNvbG5hbWVzKHBhZGpfZ2VuZV9kYXRhKSAlPiUKICBtYXBfY2hyKFwoY29sbmFtZSkgc3RyX3NwbGl0KGNvbG5hbWUsICJfIilbWzFdXVtbMV1dW1sxXV0pCgpwcmludChwYWRqX2dlbmVfZGF0YSkKYGBgCgpQbG90cyBiYXNlZCBvbiB0aGUgdHJhbnNjcmlwdHMgcGVyIG1pbGxpb24gZGF0YSBmb3IgdGhlIGdlbmVzIGRyaXZpbmcgdGhlIG1pdG9jaG9uZHJpYWwgcGF0aHdheXMuIE5vdGU6IFdvdWxkIG5lZWQgdG8gdXBkYXRlIHRpdGxlIGlmIHRoZSByZWd1bGF0ZWQgcGF0aHMgY2hhbmdlIGFuZCB0aGVyZSBhcmUgdXByZWd1bGF0ZWQgbWl0b2Nob25kcmlhbCBwYXRocwoKYGBge3J9ClRQTS5sb2cgPC0gYXMuZGF0YS5mcmFtZShUUE0ubG9nKQpUUE0ubG9nLmdlbmVzLmludGVyZXN0aW5nIDwtIGNiaW5kKG1ldGFkYXRhLmFsbCwgYXMuZGF0YS5mcmFtZSh0KFRQTS5sb2dbcm93bmFtZXMoVFBNLmxvZykgJWluJSBnZW5lc19vZl9pbnRlcmVzdCRnZW5lLF0pKSkKCiMgVG8gcGxvdCBlYWNoIGdlbmUgc2VwYXJhdGVseToKZm9yKHJvdyBpbiAxOm5yb3coZ2VuZXNfb2ZfaW50ZXJlc3QpKQp7CiAgZ2VuZSA9IGFzLmNoYXJhY3RlcihnZW5lc19vZl9pbnRlcmVzdFtyb3csICJnZW5lIl0pCiAgbnVtXzRBX2Rvd24gPSBhcy5udW1lcmljKGdlbmVzX29mX2ludGVyZXN0W3JvdywgImltcG9ydGFudF9pbl80QV9kb3duX3BhdGh3YXlzIl0pCiAgbnVtXzRCX2Rvd24gPSBhcy5udW1lcmljKGdlbmVzX29mX2ludGVyZXN0W3JvdywgImltcG9ydGFudF9pbl80Ql9kb3duX3BhdGh3YXlzIl0pCiAgCiAgIyB0aXRsZSA9IHN0cl9pbnRlcnAoIiR7Z2VuZX0gKCMgZG93bnJlZ3VsYXRlZCBwYXRocyBhZmZlY3RlZDogNEEgLSAke251bV80QV9kb3dufTsgNEIgLSAke251bV80Ql9kb3dufS4gdXByZWcgcGF0aHM6IG5vbmUpIikKICB0aXRsZSA9IGdlbmUKICBwbG90RGF0YSA8LSBUUE0ubG9nLmdlbmVzLmludGVyZXN0aW5nWywgYygiQ2VsbExpbmUiLCAiSXNvTGluZSIsIGdlbmUpXQogIGNvbG5hbWVzKHBsb3REYXRhKVszXSA8LSAibG9nLlRQTSIKICAKICAjIENvbGxlY3Qgc2lnbmlmaWNhbmNlIGRhdGEgZm9yIGVhY2ggY2VsbGxpbmUKICBzaWdEYXRhIDwtIGRhdGEuZnJhbWUoQ2VsbExpbmUgPSB1bmlxdWUocGxvdERhdGEkQ2VsbExpbmUpKQogIHNpZ0RhdGEkc2lnbmlmaWNhbnQgPSBzaWdEYXRhJENlbGxMaW5lICU+JQogICAgbWFwX2xnbChcKGNlbGxsaW5lKSAhaXMubmEocGFkal9nZW5lX2RhdGFbZ2VuZSwgY2VsbGxpbmVdKSAmJiAocGFkal9nZW5lX2RhdGFbZ2VuZSwgY2VsbGxpbmVdIDwgMC4wNSkpCiAgcGxvdERhdGEkc2lnbmlmaWNhbmNlID0gcm93bmFtZXMocGxvdERhdGEpICU+JQogICAgbWFwX2NocihcKHJvd25hbWUpIHsKICAgICAgY2VsbGxpbmUgPSBwbG90RGF0YVtyb3duYW1lLCAiQ2VsbExpbmUiXQogICAgICBzaWduaWZpY2FuY2UgPSBzaWdEYXRhW3NpZ0RhdGEkQ2VsbExpbmUgPT0gY2VsbGxpbmUsICJzaWduaWZpY2FudCJdCiAgICAgIGxhYmVsID0gaWZlbHNlKCFpcy5uYShzaWduaWZpY2FuY2UpICYmIHNpZ25pZmljYW5jZSwgIioiLCAiIikKICAgICAgcmV0dXJuKGxhYmVsKQogICAgfSkKICBwbG90RGF0YSRzaWdfaGVpZ2h0ID0gcm93bmFtZXMocGxvdERhdGEpICU+JSAjIExhYmVsIHNpZ25pZmljYW5jZSAxNSUgaGlnaGVyIHRoYW4gaGlnaGVzdCB2YWx1ZQogICAgbWFwX2RibChcKHJvd25hbWUpIHsKICAgICAgY2VsbGxpbmUgPSBwbG90RGF0YVtyb3duYW1lLCAiQ2VsbExpbmUiXQogICAgICBpc29saW5lID0gcGxvdERhdGFbcm93bmFtZSwgIklzb0xpbmUiXQogICAgICByZXBfdmFsdWVzID0gcGxvdERhdGFbcGxvdERhdGEkQ2VsbExpbmUgPT0gY2VsbGxpbmUsICJsb2cuVFBNIl0KICAgICAgaXNvbGluZV92YWx1ZXMgPSBwbG90RGF0YVtwbG90RGF0YSRJc29MaW5lID09IGlzb2xpbmUsICJsb2cuVFBNIl0KICAgICAgaGVpZ2h0ID0gbWluKGlzb2xpbmVfdmFsdWVzKSArIDEuMTUgKiAobWF4KHJlcF92YWx1ZXMpIC0gbWluKGlzb2xpbmVfdmFsdWVzKSkKICAgICAgcmV0dXJuKGhlaWdodCkKICAgIH0pCiAgCiAgcGxvdERhdGEkbGFiZWxfaGVpZ2h0ID0gcm93bmFtZXMocGxvdERhdGEpICU+JSAjIExhYmVsIG5hbWUgb2YgY2VsbGxpbmUgMTAlIGhpZ2hlciB0aGFuIGhpZ2hlc3QgdmFsdWUKICAgIG1hcF9kYmwoXChyb3duYW1lKSB7CiAgICAgIGNlbGxsaW5lID0gcGxvdERhdGFbcm93bmFtZSwgIkNlbGxMaW5lIl0KICAgICAgaXNvbGluZSA9IHBsb3REYXRhW3Jvd25hbWUsICJJc29MaW5lIl0KICAgICAgcmVwX3ZhbHVlcyA9IHBsb3REYXRhW3Bsb3REYXRhJENlbGxMaW5lID09IGNlbGxsaW5lLCAibG9nLlRQTSJdCiAgICAgIGlzb2xpbmVfdmFsdWVzID0gcGxvdERhdGFbcGxvdERhdGEkSXNvTGluZSA9PSBpc29saW5lLCAibG9nLlRQTSJdCiAgICAgIGhlaWdodCA9IG1pbihpc29saW5lX3ZhbHVlcykgKyAxLjEwICogKG1heChyZXBfdmFsdWVzKSAtIG1pbihpc29saW5lX3ZhbHVlcykpCiAgICAgIHJldHVybihoZWlnaHQpCiAgICB9KQogIAogICMgRm9yIHNldHRpbmcgeWxpbQogIHJhbmdlX3ZhbHVlcyA9IG1heChtYXgocGxvdERhdGEkbG9nLlRQTSksIG1heChwbG90RGF0YSRzaWdfaGVpZ2h0KSkgLSBtaW4ocGxvdERhdGEkbG9nLlRQTSkKICAKICBwcmludCgKICAgIGdncGxvdChwbG90RGF0YSwgYWVzKENlbGxMaW5lLCBsb2cuVFBNLCBjb2xvciA9IENlbGxMaW5lLCkpICsKICAgICAgZ2VvbV9iZWVzd2FybShhbHBoYSA9IDAuMywgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogICAgICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BLCBmaWxsID0gTkEpICsKICAgICAgZ2VvbV90ZXh0KHkgPSBwbG90RGF0YSRzaWdfaGVpZ2h0LCBzaXplID0gMTAsIGxhYmVsID0gcGxvdERhdGEkc2lnbmlmaWNhbmNlKSArCiAgICAgIGdlb21fdGV4dCh5ID0gcGxvdERhdGEkbGFiZWxfaGVpZ2h0LCBzaXplID0gMiwgbGFiZWwgPSBwbG90RGF0YSRDZWxsTGluZSkgKwogICAgICB5bGltKG1pbihwbG90RGF0YSRsb2cuVFBNKSAtIDAuMSAqIHJhbmdlX3ZhbHVlcywgbWF4KHBsb3REYXRhJGxvZy5UUE0pICsgMC4xNSAqIHJhbmdlX3ZhbHVlcykgKyAKICAgICAgdGhlbWVfY2xhc3NpYygpICsKICAgICAgdGhlbWUoYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpKSArCiAgICAgIGdndGl0bGUodGl0bGUpKQp9CmBgYAoKCjwhLS0gYGBge3J9IC0tPgo8IS0tICMgVG8gcGxvdCB0aGVtIGFsbCB0b2dldGhlcjogLS0+Cgo8IS0tICMgIyBtYWtlIGxvbmcgdmVyc2lvbiBvZiB0YWJsZSAtLT4KPCEtLSAjIGxvbmcuZGF0YSA8LSBnYXRoZXIoVFBNLmxvZy5nZW5lcy5pbnRlcmVzdGluZywga2V5PSJHZW5lIiwgdmFsdWU9ImxvZ1RQTSIsIEFBUlMyOllBUlMyKSAtLT4KPCEtLSAjICAgICAgLS0+CjwhLS0gIyBwbG90IDwtIGdncGxvdChsb25nLmRhdGEsIGFlcyhDZWxsTGluZSwgbG9nVFBNLCBmaWxsID0gR2VuZSwgY29sb3IgPSBDZWxsTGluZSwpKSArIC0tPgo8IS0tICMgICAgICAgIyBnZW9tX2JlZXN3YXJtKGFscGhhID0gMC4zKSArIC0tPgo8IS0tICMgICAgICAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSwgZmlsbCA9IE5BKSArIC0tPgo8IS0tICMgICAgICAgdGhlbWVfY2xhc3NpYygpICsgLS0+CjwhLS0gIyAgICAgICB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLCAtLT4KPCEtLSAjICAgICAgICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwgLS0+CjwhLS0gIyAgICAgICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpKSArIC0tPgo8IS0tICMgICAgICAgZmFjZXRfd3JhcF9wYWdpbmF0ZSh2YXJzKEdlbmUpLCBucm93ID0gMSwgbmNvbCA9IDUpIC0tPgo8IS0tICMgIC0tPgo8IS0tICMgZm9yKGkgaW4gMTpuX3BhZ2VzKHBsb3QpKSAtLT4KPCEtLSAjICAgcHJpbnQoIC0tPgo8IS0tICMgICAgZ2dwbG90KGxvbmcuZGF0YSwgYWVzKENlbGxMaW5lLCBsb2dUUE0sIGZpbGwgPSBHZW5lLCBjb2xvciA9IENlbGxMaW5lLCkpICsgLS0+CjwhLS0gIyAgICAgICAjIGdlb21fYmVlc3dhcm0oYWxwaGEgPSAwLjMpICsgLS0+CjwhLS0gIyAgICAgICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BLCBmaWxsID0gTkEpICsgLS0+CjwhLS0gIyAgICAgICB0aGVtZV9jbGFzc2ljKCkgKyAtLT4KPCEtLSAjICAgICAgIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksIC0tPgo8IS0tICMgICAgICAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLCAtLT4KPCEtLSAjICAgICAgICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCkpICsgLS0+CjwhLS0gIyAgICAgICBmYWNldF93cmFwX3BhZ2luYXRlKHZhcnMoR2VuZSksIG5yb3cgPSAxLCBuY29sID0gNSwgcGFnZSA9IGkpKSAtLT4KPCEtLSBgYGAgLS0+Cg==